#include <jni.h>

#include "ffmpeg.h"
#include "libavutil/ffversion.h"
#include <android/log.h>

#define TAG "XCTT"

//#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__)

#define ALOGE(...) __android_log_print(ANDROID_LOG_ERROR, TAG,  __VA_ARGS__)
#define ALOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG,  __VA_ARGS__)
#define ALOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG,  __VA_ARGS__)
#define ALOGW(...) __android_log_print(ANDROID_LOG_WARN, TAG,  __VA_ARGS__)
#define ALOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, TAG,  __VA_ARGS__)

JNIEXPORT jstring JNICALL
Java_cn_changsha_xczxapp_ffmpeg_FFmpegNativeBridge_getFFmpegVersion(JNIEnv *env, jclass type) {
//    char str[25];
//    sprintf(str, "%d", avcodec_version());
//    return (*env)->NewStringUTF(env, str);
    return (*env)->NewStringUTF(env, FFMPEG_VERSION);
}

JNIEXPORT jstring JNICALL
Java_cn_changsha_xczxapp_ffmpeg_FFmpegNativeBridge_getCheckCode(JNIEnv *env, jclass type,
                                                                jstring code_) {
    const  char *str = NULL;
    str = (*env)->GetStringUTFChars(env, code_, 0);
    if (str == NULL) {
        return NULL;/* OutOfMemoryError already thrown */
    }
    char buff[256];
    sprintf(buff, "xczx%s123", str);
    (*env)->ReleaseStringUTFChars(env, code_, str);
    return (*env)->NewStringUTF(env, buff);
}


static JavaVM *jvm = NULL;//java虚拟机
static jclass m_clazz = NULL;//当前类(面向java)
static JNIEnv *m_env = NULL;

void callJavaMethod(char *ret){
    int result = 0;
    char timeStr[10] = "time=";
    char *q = strstr(ret, timeStr);
    if(q != NULL) {//日志信息中若包含"time="字符串
        char str[14] = {0};
        strncpy(str, q, 13);
        int h =(str[5]-'0')*10+(str[6]-'0');
        int m =(str[8]-'0')*10+(str[9]-'0');
        int s =(str[11]-'0')*10+(str[12]-'0');
        result = s + m*60 + h*60*60;
        if (m_clazz == NULL) {
            return;
        }
        //获取java方法
        jmethodID methodID = (*m_env)->GetStaticMethodID(m_env, m_clazz, "onProgress", "(I)V");
        if (methodID == NULL) {
            return;
        }
        //调用该方法
        (*m_env)->CallStaticVoidMethod(m_env, m_clazz, methodID, result);
    } else {
        return;
    }
}

// 是否启用 debug 默认不启用
jboolean FFMPEG_ANDROID_DEBUG = 0;
static void ffmpeg_android_log_callback(void *ptr, int level, const char *fmt, va_list vl){

    static int print_prefix = 1;
    static int count;
    static char prev[1024];
    char line[1024];
    static int is_atty;

    av_log_format_line(ptr, level, fmt, vl, line, sizeof(line), &print_prefix);

    strcpy(prev, line);

//        if (level <= AV_LOG_WARNING){
//            ALOGE("%s", line);
//        }else{
//            ALOGD("%s", line);
//            callJavaMethod(line);
//        }

    //ALOGE("输出：%s",line);

    if (level == AV_LOG_INFO) {
        callJavaMethod(line);
    }

    if (FFMPEG_ANDROID_DEBUG){
        switch(level) {
            case AV_LOG_DEBUG:
                ALOGD("输出：%s",line);
                break;
            case AV_LOG_VERBOSE:
                ALOGV("输出：%s",line);
                break;
            case AV_LOG_INFO:
                ALOGI("输出：%s",line);
                break;
            case AV_LOG_WARNING:
                ALOGW("输出：%s",line);
                break;
            case AV_LOG_ERROR:
                ALOGE("输出：%s",line);
                break;
        }
    }

}

JNIEXPORT jint JNICALL
Java_cn_changsha_xczxapp_ffmpeg_FFmpegNativeBridge_ffmpegExec(JNIEnv *env, jclass type, jboolean isDebug,
                                                      jobjectArray command) {

    //获取java虚拟机，在jni的c线程中不允许使用共用的env环境变量 但JavaVM在整个jvm中是共用的 可通过保存JavaVM指针,到时候再通过JavaVM指针取出JNIEnv *env
    (*env)->GetJavaVM(env, &jvm);
    //获取调用此方法的java类，ICS之前(你可把NDK sdk版本改成低于11) 可以写m_clazz = clazz直接赋值,  然而ICS(sdk11) 后便改变了这一机制,在线程中回调java时 不能直接共用变量 必须使用NewGlobalRef创建全局对象
    m_clazz = (*env)->NewGlobalRef(env, type);
    m_env = env;

    FFMPEG_ANDROID_DEBUG = isDebug;

//    if (isDebug){
//        av_log_set_callback(ffmpeg_android_log_callback);
//    } else {
//        av_log_set_callback(NULL);
//    }

    av_log_set_callback(ffmpeg_android_log_callback);

    int argc = (*env)->GetArrayLength(env, command);
    char *argv[argc];
    int i;
    for (i = 0; i < argc; i++) {
        jstring js = (jstring) (*env)->GetObjectArrayElement(env, command, i);
        argv[i] = (char*) (*env)->GetStringUTFChars(env, js, 0);
        if (FFMPEG_ANDROID_DEBUG) {
            ALOGE("ffmpeg命令行=%s",argv[i]);
        }
    }
    int ret = ffmpeg_exec(argc, argv);
    return ret;

}